/*
 * Copyright 2013 Walter Lütgenau.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package offset.nodes.client.vdialog.view.navigation;

import java.util.Enumeration;
import java.util.HashMap;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import offset.nodes.client.dialog.navigation.model.NodeSelectionListener;
import offset.nodes.client.dialog.navigation.view.AbstractCardPanel;
import offset.nodes.client.dialog.navigation.view.ElementInfo;
import offset.nodes.client.dialog.navigation.view.NodeInfo;
import offset.nodes.client.dialog.navigation.view.PropertyInfo;

/**
 *
 * @author Walter Lütgenau
 */
public class VirtualPagePanel extends AbstractCardPanel {

    HashMap<String, DefaultMutableTreeNode> currentNodes = new HashMap<String, DefaultMutableTreeNode>();
    DefaultMutableTreeNode root = null;
    NodeSelectionListener nodeSelectionListener;
    Object selectedUserObject;

    @Override
    public String getCardName() {
        return "virtual";
    }

    /**
     * The tree selection listener used to notify the node selection listener
     */
    protected class TreeSelectionHandler implements TreeSelectionListener {

        public void valueChanged(TreeSelectionEvent e) {
            if (virtualTree.getSelectionCount() != 1)
                return;

            TreePath path = virtualTree.getSelectionPath();
            DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
            
            String name = null;
            
            if (node.getUserObject() instanceof NodeInfo) {
                NodeInfo nodeUserObject = (NodeInfo) node.getUserObject();
                
                name = nodeUserObject.getName();
                selectedUserObject = nodeUserObject.getUserObject();
            } else if (node.getUserObject() instanceof PropertyInfo) {
                PropertyInfo propertyUserObject = (PropertyInfo) node.getUserObject();
                
                name = propertyUserObject.getName();
                selectedUserObject = propertyUserObject.getUserObject();
            }

            if (nodeSelectionListener != null) {
                nodeSelectionListener.nodeSelected(name);
            }
        }
    }

    /**
     * Creates new form HeadingPanel
     */
    public VirtualPagePanel() {
        initComponents();
        virtualTree.setCellRenderer(new VirtualElementRenderer());
        root = (DefaultMutableTreeNode) virtualTree.getModel().getRoot();
        root.setUserObject(new NodeInfo(null, "", ""));
    }

    /**
     * Set a node selection listener
     *
     * @param nodeSelectionListener
     */
    public void setNodeSelectionListener(NodeSelectionListener nodeSelectionListener) {
        this.nodeSelectionListener = nodeSelectionListener;
        virtualTree.addTreeSelectionListener(new TreeSelectionHandler());
    }

    /**
     * Start to add data for a new page
     */
    public void start() {
        root = (DefaultMutableTreeNode) virtualTree.getModel().getRoot();
        root.removeAllChildren();
        root.setUserObject(new NodeInfo(null, "", ""));
        currentNodes = new HashMap<String, DefaultMutableTreeNode>();
    }

    /**
     * Finish to add data for a new page
     */
    public void end() {
        DefaultMutableTreeNode root = (DefaultMutableTreeNode) virtualTree.getModel().getRoot();
        
        ((DefaultTreeModel) virtualTree.getModel()).nodeStructureChanged(root);        
        expandNodes(root);
    }

    protected void expandNodes(TreeNode node) {
        for (Enumeration children = node.children(); children.hasMoreElements();) {
            DefaultMutableTreeNode dtm = (DefaultMutableTreeNode) children.nextElement();
            if (!dtm.isLeaf()) {
                TreePath tp = new TreePath(dtm.getPath());
                virtualTree.expandPath(tp);
                
                expandNodes(dtm);

            }
        }
    }

    public Object getSelectedUserObject() {
        return selectedUserObject;
    }
    
    /**
     * Add an element of the virtual page associated to a node
     * 
     * @param parent the parent
     * @param nodeType the node type
     * @param name the name of the node
     * @return the new node object
     */
    public void addNode(Object parent, Object node, String query, String nodeType, String name) {
        DefaultMutableTreeNode child = new DefaultMutableTreeNode(new NodeInfo(node, nodeType, name));
        
        DefaultMutableTreeNode current = currentNodes.get(query);
        if (current == null) {
            if (query != null) {
                current = new DefaultMutableTreeNode(new NodeInfo(null, "", ""));
                root.add(current);
            } else
                current = root;
            
            currentNodes.put(query, current);
        }
                    
        ElementInfo currentElement = (ElementInfo) current.getUserObject();
        while (currentElement != null 
                && currentElement.getUserObject() != null
                && currentElement.getUserObject() != parent) {
            current = (DefaultMutableTreeNode) current.getParent();
            currentElement = (ElementInfo) current.getUserObject();
        }

        current.add(child);
        currentNodes.put(query, child);
    }
    
    /**
     * Add an element of the virtual page associated to a property 
     * 
     * @param node the parent node
     * @param propertyType the type of the property 
     * @param name the name of the property
     */
    public void addProperty(Object parent, Object node, String query, int propertyType, String name) {
        DefaultMutableTreeNode child = new DefaultMutableTreeNode(new PropertyInfo(node, propertyType, name));
        
       DefaultMutableTreeNode current = currentNodes.get(query);    
       if (current == null)
           return; // should not happen

        ElementInfo currentElement = (ElementInfo) current.getUserObject();
        while (currentElement != null && currentElement.getUserObject() != parent) {
            current = (DefaultMutableTreeNode) current.getParent();
            currentElement = (ElementInfo) current.getUserObject();
        }

        current.add(child);
        currentNodes.put(query, child);
    }

    /**
     * This method is called from within the constructor to initialize the form. WARNING: Do NOT
     * modify this code. The content of this method is always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane2 = new javax.swing.JScrollPane();
        virtualTree = new javax.swing.JTree();

        setLayout(new java.awt.BorderLayout());

        jScrollPane2.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));

        javax.swing.tree.DefaultMutableTreeNode treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("root");
        virtualTree.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1));
        virtualTree.setRowHeight(0);
        jScrollPane2.setViewportView(virtualTree);

        add(jScrollPane2, java.awt.BorderLayout.CENTER);
    }// </editor-fold>//GEN-END:initComponents
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JTree virtualTree;
    // End of variables declaration//GEN-END:variables
}
